import WxPaySignUtil from './wxpay-sign.js'

/**
 * 微信支付调试工具类
 * 用于排查微信支付问题和错误诊断
 */
export class WxPayDebugUtil {
  
  /**
   * 常见错误码对照表
   */
  static ERROR_CODES = {
    // 通用错误
    'SUCCESS': '成功',
    'FAIL': '失败',
    'SYSTEMERROR': '系统错误，请稍后重试',
    'PARAM_ERROR': '参数错误',
    'ORDERPAID': '订单已支付',
    'ORDERCLOSED': '订单已关闭',
    'ORDERREVERSED': '订单已撤销',
    'NOTSUPORTCARD': '不支持卡类型',
    'NOAUTH': '商户无权限',
    'NOTENOUGH': '余额不足',
    'INVALID_REQUEST': '无效请求',
    'FREQUENCY_LIMITED': '频率限制',
    'BANKERROR': '银行系统异常',
    'USERPAYING': '用户支付中',
    'AUTH_CODE_ERROR': '授权码参数错误',
    'AUTH_CODE_EXPIRE': '授权码过期',
    'XML_FORMAT_ERROR': 'XML格式错误',
    'REQUIRE_POST_METHOD': '请使用post方法',
    'SIGNERROR': '签名错误',
    'LACK_PARAMS': '缺少参数',
    'NOT_UTF8': '编码格式错误',
    'BUYER_MISMATCH': '支付帐号错误',
    'APPID_NOT_EXIST': 'APPID不存在',
    'MCHID_NOT_EXIST': 'MCHID不存在',
    'APPID_MCHID_NOT_MATCH': 'appid和mch_id不匹配',
    'OUT_TRADE_NO_USED': '商户订单号重复',
    'BIZERR_NEED_RETRY': '退款业务流程错误，需要商户触发重试来解决',
    'TRADE_OVERDUE': '订单超时',
    'ERROR': '业务错误',
    'USER_ACCOUNT_ABNORMAL': '用户账户异常',
    'INVALID_TRANSACTIONID': '无效transaction_id',
    'ORDERNOTEXIST': '订单不存在',
    'REFUNDNOTEXIST': '退款订单查询失败'
  }

  /**
   * 检查配置参数
   */
  static validateConfig(config) {
    const errors = []
    const warnings = []

    // 必填参数检查
    if (!config.appid) {
      errors.push('缺少 appid 参数')
    } else if (!config.appid.startsWith('wx')) {
      errors.push('appid 格式错误，应该以 wx 开头')
    } else if (config.appid.length !== 18) {
      warnings.push('appid 长度异常，标准长度为18位')
    }

    if (!config.mch_id) {
      errors.push('缺少 mch_id 参数')
    } else if (!/^\d{10}$/.test(config.mch_id)) {
      errors.push('mch_id 格式错误，应该是10位数字')
    }

    if (!config.key) {
      errors.push('缺少 key 参数（API密钥）')
    } else if (config.key.length !== 32) {
      errors.push('key 长度错误，应该是32位字符')
    }

    if (!config.notify_url) {
      errors.push('缺少 notify_url 参数')
    } else if (!config.notify_url.startsWith('https://')) {
      warnings.push('notify_url 建议使用 https 协议')
    }

    return { errors, warnings }
  }

  /**
   * 检查订单参数
   */
  static validateOrderInfo(orderInfo) {
    const errors = []
    const warnings = []

    // 必填参数检查
    if (!orderInfo.body) {
      errors.push('缺少 body 参数（商品描述）')
    } else if (orderInfo.body.length > 128) {
      errors.push('body 长度超过限制（最大128字符）')
    }

    if (!orderInfo.out_trade_no) {
      errors.push('缺少 out_trade_no 参数（商户订单号）')
    } else if (orderInfo.out_trade_no.length > 32) {
      errors.push('out_trade_no 长度超过限制（最大32字符）')
    }

    if (!orderInfo.total_fee) {
      errors.push('缺少 total_fee 参数（订单金额）')
    } else {
      const fee = parseInt(orderInfo.total_fee)
      if (isNaN(fee) || fee <= 0) {
        errors.push('total_fee 必须是大于0的整数')
      } else if (fee > 100000000) {
        errors.push('total_fee 超过限制（最大1亿分）')
      }
    }

    if (!orderInfo.trade_type) {
      errors.push('缺少 trade_type 参数')
    } else if (!['APP', 'JSAPI', 'NATIVE', 'MWEB'].includes(orderInfo.trade_type)) {
      errors.push('trade_type 参数值无效')
    }

    // JSAPI支付需要openid
    if (orderInfo.trade_type === 'JSAPI' && !orderInfo.openid) {
      errors.push('JSAPI支付需要提供 openid 参数')
    }

    return { errors, warnings }
  }

  /**
   * 生成诊断报告
   */
  static generateDiagnosticReport(config, orderInfo) {
    const report = {
      timestamp: new Date().toISOString(),
      config: this.validateConfig(config),
      order: this.validateOrderInfo(orderInfo),
      suggestions: []
    }

    // 生成建议
    if (report.config.errors.length > 0) {
      report.suggestions.push('请检查微信支付配置参数')
    }

    if (report.order.errors.length > 0) {
      report.suggestions.push('请检查订单参数')
    }

    if (report.config.warnings.length > 0 || report.order.warnings.length > 0) {
      report.suggestions.push('请注意警告信息，可能影响支付成功率')
    }

    return report
  }

  /**
   * 模拟统一下单请求
   */
  static async simulateUnifiedOrder(config, orderInfo) {
    try {
      // 1. 参数验证
      const diagnostic = this.generateDiagnosticReport(config, orderInfo)
      if (diagnostic.config.errors.length > 0 || diagnostic.order.errors.length > 0) {
        return {
          success: false,
          error: 'PARAM_ERROR',
          message: '参数验证失败',
          diagnostic
        }
      }

      // 2. 生成统一下单参数
      const unifiedOrderResult = WxPaySignUtil.prepareUnifiedOrderSign(config, orderInfo)
      
      // 3. 模拟网络请求（这里需要替换为实际的后端接口）
      const response = await this.mockUnifiedOrderRequest(unifiedOrderResult.params)
      
      return {
        success: response.return_code === 'SUCCESS' && response.result_code === 'SUCCESS',
        data: response,
        diagnostic,
        requestParams: unifiedOrderResult.params,
        signInfo: unifiedOrderResult.signInfo
      }
    } catch (error) {
      return {
        success: false,
        error: 'SYSTEMERROR',
        message: error.message,
        diagnostic: this.generateDiagnosticReport(config, orderInfo)
      }
    }
  }

  /**
   * 模拟统一下单请求（实际项目中应该调用后端接口）
   */
  static async mockUnifiedOrderRequest(params) {
    // 模拟网络延迟
    await new Promise(resolve => setTimeout(resolve, 1000))

    // 模拟不同的返回结果
    const random = Math.random()
    
    if (random < 0.7) {
      // 70% 概率成功
      return {
        return_code: 'SUCCESS',
        result_code: 'SUCCESS',
        appid: params.appid,
        mch_id: params.mch_id,
        nonce_str: params.nonce_str,
        sign: 'mock_sign',
        prepay_id: 'wx' + Date.now() + Math.random().toString(36).substr(2, 9),
        trade_type: params.trade_type
      }
    } else if (random < 0.85) {
      // 15% 概率签名错误
      return {
        return_code: 'FAIL',
        return_msg: '签名错误',
        err_code: 'SIGNERROR',
        err_code_des: '参数签名结果不正确'
      }
    } else if (random < 0.95) {
      // 10% 概率参数错误
      return {
        return_code: 'FAIL',
        return_msg: '参数错误',
        err_code: 'PARAM_ERROR',
        err_code_des: '参数格式校验错误'
      }
    } else {
      // 5% 概率系统错误
      return {
        return_code: 'FAIL',
        return_msg: '系统错误',
        err_code: 'SYSTEMERROR',
        err_code_des: '系统超时'
      }
    }
  }

  /**
   * 解析错误信息
   */
  static parseError(errorResponse) {
    const error = {
      code: errorResponse.err_code || errorResponse.return_code || 'UNKNOWN',
      message: errorResponse.err_code_des || errorResponse.return_msg || '未知错误',
      suggestion: ''
    }

    // 根据错误码提供解决建议
    switch (error.code) {
      case 'SIGNERROR':
        error.suggestion = '1. 检查API密钥是否正确\n2. 确认参数顺序和格式\n3. 检查字符编码是否为UTF-8'
        break
      case 'PARAM_ERROR':
        error.suggestion = '1. 检查必填参数是否完整\n2. 确认参数格式是否正确\n3. 检查参数长度限制'
        break
      case 'APPID_NOT_EXIST':
        error.suggestion = '1. 确认AppID是否正确\n2. 检查是否已在微信开放平台注册'
        break
      case 'MCHID_NOT_EXIST':
        error.suggestion = '1. 确认商户号是否正确\n2. 检查商户号状态是否正常'
        break
      case 'APPID_MCHID_NOT_MATCH':
        error.suggestion = '1. 确认AppID和商户号是否匹配\n2. 检查商户平台绑定关系'
        break
      case 'OUT_TRADE_NO_USED':
        error.suggestion = '1. 更换商户订单号\n2. 检查订单号生成逻辑'
        break
      case 'NOAUTH':
        error.suggestion = '1. 检查商户权限设置\n2. 确认产品功能是否开通'
        break
      case 'SYSTEMERROR':
        error.suggestion = '1. 稍后重试\n2. 检查网络连接\n3. 联系微信技术支持'
        break
      default:
        error.suggestion = '请参考微信支付官方文档或联系技术支持'
    }

    return error
  }

  /**
   * 生成调试信息
   */
  static generateDebugInfo(config, orderInfo, response) {
    const debugInfo = {
      timestamp: new Date().toISOString(),
      request: {
        config: { ...config, key: '***' }, // 隐藏敏感信息
        orderInfo
      },
      response,
      diagnostic: this.generateDiagnosticReport(config, orderInfo)
    }

    if (!response.success) {
      debugInfo.error = this.parseError(response.data || response)
    }

    return debugInfo
  }

  /**
   * 格式化调试信息为可读文本
   */
  static formatDebugInfo(debugInfo) {
    let text = `=== 微信支付调试信息 ===\n`
    text += `时间: ${debugInfo.timestamp}\n\n`

    text += `=== 请求参数 ===\n`
    text += `AppID: ${debugInfo.request.config.appid}\n`
    text += `商户号: ${debugInfo.request.config.mch_id}\n`
    text += `商品描述: ${debugInfo.request.orderInfo.body}\n`
    text += `订单号: ${debugInfo.request.orderInfo.out_trade_no}\n`
    text += `金额: ${debugInfo.request.orderInfo.total_fee}分\n`
    text += `支付类型: ${debugInfo.request.orderInfo.trade_type}\n\n`

    if (debugInfo.diagnostic.config.errors.length > 0) {
      text += `=== 配置错误 ===\n`
      debugInfo.diagnostic.config.errors.forEach(error => {
        text += `❌ ${error}\n`
      })
      text += `\n`
    }

    if (debugInfo.diagnostic.order.errors.length > 0) {
      text += `=== 订单错误 ===\n`
      debugInfo.diagnostic.order.errors.forEach(error => {
        text += `❌ ${error}\n`
      })
      text += `\n`
    }

    if (debugInfo.error) {
      text += `=== 错误信息 ===\n`
      text += `错误码: ${debugInfo.error.code}\n`
      text += `错误描述: ${debugInfo.error.message}\n`
      text += `解决建议:\n${debugInfo.error.suggestion}\n\n`
    }

    if (debugInfo.diagnostic.suggestions.length > 0) {
      text += `=== 建议 ===\n`
      debugInfo.diagnostic.suggestions.forEach(suggestion => {
        text += `💡 ${suggestion}\n`
      })
    }

    return text
  }

  /**
   * 网络连接测试
   */
  static async testNetworkConnection() {
    const testUrls = [
      'https://api.mch.weixin.qq.com',
      'https://api.weixin.qq.com',
      'https://pay.weixin.qq.com'
    ]

    const results = []
    
    for (const url of testUrls) {
      try {
        const startTime = Date.now()
        const response = await uni.request({
          url: url,
          method: 'GET',
          timeout: 5000
        })
        const endTime = Date.now()
        
        results.push({
          url,
          success: true,
          responseTime: endTime - startTime,
          status: response.statusCode
        })
      } catch (error) {
        results.push({
          url,
          success: false,
          error: error.message
        })
      }
    }

    return results
  }

  /**
   * 签名验证诊断
   * @param {Object} config - 微信支付配置
   * @param {Object} orderInfo - 订单信息
   * @param {string} generatedSign - 生成的签名
   * @returns {Object} 诊断结果
   */
  static diagnoseSignVerification(config, orderInfo, generatedSign) {
    const issues = []
    const suggestions = []
    
    try {
      // 1. 检查配置完整性
      if (!config.appid || config.appid.trim() === '') {
        issues.push('AppID为空或无效')
        suggestions.push('请检查AppID是否正确填写')
      } else if (!config.appid.startsWith('wx')) {
        issues.push('AppID格式错误，应该以wx开头')
        suggestions.push('请检查AppID格式，正确格式如：wxd930ea5d5a258f4f')
      }
      
      if (!config.mch_id || config.mch_id.trim() === '') {
        issues.push('商户号为空')
        suggestions.push('请填写正确的微信支付商户号')
      } else if (!/^\d+$/.test(config.mch_id)) {
        issues.push('商户号格式错误，应该是纯数字')
        suggestions.push('商户号应该是10位纯数字，如：1900000109')
      }
      
      if (!config.key || config.key.length !== 32) {
        issues.push('API密钥长度错误')
        suggestions.push('API密钥应该是32位字符串')
      }
      
      // 2. 检查订单信息
      if (!orderInfo.out_trade_no) {
        issues.push('订单号为空')
        suggestions.push('请生成订单号')
      }
      
      if (!orderInfo.body || orderInfo.body.trim() === '') {
        issues.push('商品描述为空')
        suggestions.push('请填写商品描述')
      }
      
      if (!orderInfo.total_fee || orderInfo.total_fee <= 0) {
        issues.push('支付金额无效')
        suggestions.push('支付金额必须大于0，单位为分')
      }
      
      // 3. 生成标准签名参数进行对比
      const standardParams = {
        appid: config.appid,
        mch_id: config.mch_id,
        nonce_str: 'test123456789012345678901234567890',
        body: orderInfo.body,
        out_trade_no: orderInfo.out_trade_no,
        total_fee: parseInt(orderInfo.total_fee),
        spbill_create_ip: orderInfo.spbill_create_ip || '127.0.0.1',
        notify_url: config.notify_url,
        trade_type: orderInfo.trade_type || 'APP'
      }
      
      // 4. 重新计算签名
      const keys = Object.keys(standardParams)
        .filter(key => standardParams[key] !== undefined && standardParams[key] !== null && standardParams[key] !== '')
        .sort()
      
      const signString = keys.map(key => `${key}=${standardParams[key]}`).join('&') + `&key=${config.key}`
      
      // 5. 检查常见签名问题
      const signatureAnalysis = {
        parametersCount: keys.length,
        signString: signString,
        expectedSignLength: 32,
        actualSignLength: generatedSign ? generatedSign.length : 0
      }
      
      if (generatedSign && generatedSign.length !== 32) {
        issues.push(`签名长度错误：期望32位，实际${generatedSign.length}位`)
        suggestions.push('检查MD5计算是否正确，确保转换为大写')
      }
      
      if (signString.includes('undefined') || signString.includes('null')) {
        issues.push('签名字符串包含无效值')
        suggestions.push('检查所有参数是否已正确设置')
      }
      
      // 6. 生成修复建议
      if (issues.length === 0) {
        suggestions.push('配置看起来正常，可能是网络问题或微信服务器问题')
        suggestions.push('尝试重新生成签名或检查服务器时间')
      }
      
      return {
        status: issues.length === 0 ? 'success' : 'error',
        issues: issues,
        suggestions: suggestions,
        signatureAnalysis: signatureAnalysis,
        testSignString: signString,
        configValidation: {
          appidValid: config.appid && config.appid.startsWith('wx'),
          mchIdValid: config.mch_id && /^\d+$/.test(config.mch_id),
          keyValid: config.key && config.key.length === 32,
          orderValid: orderInfo.out_trade_no && orderInfo.body && orderInfo.total_fee > 0
        }
      }
      
    } catch (error) {
      return {
        status: 'error',
        issues: [`诊断过程出错: ${error.message}`],
        suggestions: ['请检查输入参数是否正确'],
        error: error.message
      }
    }
  }
}

export default WxPayDebugUtil 